import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.layout.Pane;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.List;

public class homework_14 extends Application {

    @Override
    public void start(Stage primaryStage) {
        // 创建一个 Pane 作为根节点
        Pane root = new Pane();
        // 设置 Pane 的背景颜色为天蓝色
        root.setStyle("-fx-background-color: #87CEEB;");

        // 创建一个椭圆作为头部
        Ellipse head = new Ellipse(400, 300, 180, 200);
        // 设置头部的填充颜色为粉色
        head.setFill(Color.PINK);
        // 设置头部的边框颜色为深红色
        head.setStroke(Color.DARKRED);
        // 设置头部边框的宽度为 2
        head.setStrokeWidth(2);

        // 创建鼻子、眼睛、耳朵、嘴巴、身体和腿的图形元素
        Group nose = createNose();
        Group eyes = createEyes();
        Path leftEar = createEar(250, 150);
        Path rightEar = createEar(550, 150);
        Path mouth = createMouth();
        Path body = createBody();
        Group legs = createLegs();

        // 将所有图形元素添加到根节点中
        root.getChildren().addAll(body, head, leftEar, rightEar, nose, eyes, mouth, legs);

        // 创建一个场景，设置其根节点和大小
        Scene scene = new Scene(root, 800, 600);
        // 设置舞台的标题
        primaryStage.setTitle("JavaFX Peppa Pig (B-Spline)");
        // 将场景设置到舞台上
        primaryStage.setScene(scene);
        // 显示舞台
        primaryStage.show();
    }

    // B 样条曲线段的方法
    private List<PathElement> generateBSplineSegment(double p0x, double p0y,
                                                     double p1x, double p1y,
                                                     double p2x, double p2y,
                                                     double p3x, double p3y,
                                                     int steps) {
        // 创建一个存储路径元素的列表
        List<PathElement> elements = new ArrayList<>();
        // 循环计算 B 样条曲线上的点
        for (int i = 0; i <= steps; i++) {
            // 计算参数 t 的值
            double t = (double) i / steps;
            // 根据 B 样条曲线的公式计算 x 坐标
            double x = (-p0x + 3*p1x - 3*p2x + p3x)*t*t*t/6 + (3*p0x - 6*p1x + 3*p2x)*t*t/6 + (-3*p0x + 3*p2x)*t/6 + (p0x + 4*p1x + p2x)/6;
            // 根据 B 样条曲线的公式计算 y 坐标
            double y = (-p0y + 3*p1y - 3*p2y + p3y)*t*t*t/6 + (3*p0y - 6*p1y + 3*p2y)*t*t/6 + (-3*p0y + 3*p2y)*t/6 + (p0y + 4*p1y + p2y)/6;
            // 如果是第一个点，添加 MoveTo 元素
            if (i == 0) {
                elements.add(new MoveTo(x, y));
            } else {
                // 否则添加 LineTo 元素
                elements.add(new LineTo(x, y));
            }
        }
        // 返回路径元素列表
        return elements;
    }

    // 创建耳朵的方法
    private Path createEar(double x, double y) {
        // 创建一个 Path 对象作为耳朵
        Path ear = new Path();
        // 设置耳朵的填充颜色为粉色
        ear.setFill(Color.PINK);
        // 设置耳朵的边框颜色为深红色
        ear.setStroke(Color.DARKRED);
        // 设置耳朵边框的宽度为 2
        ear.setStrokeWidth(2);
        // 添加第一段 B 样条曲线到耳朵的路径中
        ear.getElements().addAll(generateBSplineSegment(x, y, x-50, y-80, x-80, y+50, x, y+100, 20));
        // 添加第二段 B 样条曲线到耳朵的路径中
        ear.getElements().addAll(generateBSplineSegment(x, y+100, x+30, y+80, x+20, y-30, x, y, 20));
        // 返回耳朵的 Path 对象
        return ear;
    }

    // 创建身体的方法
    private Path createBody() {
        // 创建一个 Path 对象作为身体
        Path body = new Path();
        // 设置身体的填充颜色为红色
        body.setFill(Color.RED);
        // 设置身体的边框颜色为深红色
        body.setStroke(Color.DARKRED);
        // 移动到起始点
        body.getElements().add(new MoveTo(300, 450));
        // 添加第一段 B 样条曲线到身体的路径中
        body.getElements().addAll(generateBSplineSegment(300, 450, 250, 500, 250, 600, 300, 650, 20));
        // 添加一条直线到路径中
        body.getElements().add(new LineTo(500, 650));
        // 添加第二段 B 样条曲线到身体的路径中
        body.getElements().addAll(generateBSplineSegment(500, 650, 550, 600, 550, 500, 500, 450, 20));
        // 闭合路径
        body.getElements().add(new ClosePath());
        // 返回身体的 Path 对象
        return body;
    }

    // 创建腿的方法
    private Group createLegs() {
        // 创建前腿的 Path 对象
        Path frontLeg = new Path();
        // 设置前腿的边框颜色为粉色
        frontLeg.setStroke(Color.PINK);
        // 设置前腿边框的宽度为 25
        frontLeg.setStrokeWidth(25);
        // 添加 B 样条曲线到前腿的路径中
        frontLeg.getElements().addAll(generateBSplineSegment(350, 600, 340, 680, 380, 680, 370, 600, 20));

        // 创建后腿的 Path 对象
        Path backLeg = new Path();
        // 设置后腿的边框颜色为粉色
        backLeg.setStroke(Color.PINK);
        // 设置后腿边框的宽度为 25
        backLeg.setStrokeWidth(25);
        // 添加 B 样条曲线到后腿的路径中
        backLeg.getElements().addAll(generateBSplineSegment(450, 600, 440, 680, 480, 680, 470, 600, 20));

        // 将前腿和后腿组合成一个 Group 对象
        return new Group(frontLeg, backLeg);
    }

    // 创建嘴巴的方法
    private Path createMouth() {
        // 创建一个 Path 对象作为嘴巴
        Path mouth = new Path();
        // 设置嘴巴的边框颜色为红色
        mouth.setStroke(Color.RED);
        // 设置嘴巴边框的宽度为 3
        mouth.setStrokeWidth(3);
        // 不填充嘴巴
        mouth.setFill(null);
        // 添加 B 样条曲线到嘴巴的路径中
        mouth.getElements().addAll(generateBSplineSegment(300, 420, 350, 470, 450, 470, 500, 420, 20));
        // 返回嘴巴的 Path 对象
        return mouth;
    }

    // 创建鼻子的方法
    private Group createNose() {
        // 创建鼻子的基础椭圆
        Ellipse noseBase = new Ellipse(400, 400, 40, 30);
        // 设置鼻子基础椭圆的填充颜色为浅粉色
        noseBase.setFill(Color.LIGHTPINK);
        // 创建左鼻孔的圆形
        Circle leftNostril = new Circle(380, 410, 8);
        // 创建右鼻孔的圆形
        Circle rightNostril = new Circle(420, 410, 8);
        // 将鼻子基础椭圆和左右鼻孔组合成一个 Group 对象
        return new Group(noseBase, leftNostril, rightNostril);
    }

    // 创建眼睛的方法
    private Group createEyes() {
        // 创建左眼睛的椭圆
        Ellipse leftEye = new Ellipse(320, 250, 25, 35);
        // 创建右眼睛的椭圆
        Ellipse rightEye = new Ellipse(480, 250, 25, 35);
        // 设置左眼睛的填充颜色为白色
        leftEye.setFill(Color.WHITE);
        // 设置右眼睛的填充颜色为白色
        rightEye.setFill(Color.WHITE);
        // 创建左瞳孔的圆形
        Circle leftPupil = new Circle(320, 270, 12);
        // 创建右瞳孔的圆形
        Circle rightPupil = new Circle(480, 270, 12);
        // 将左右眼睛和左右瞳孔组合成一个 Group 对象
        return new Group(leftEye, rightEye, leftPupil, rightPupil);
    }

    // 主方法，程序的入口点
    public static void main(String[] args) {
        // 启动 JavaFX 应用程序
        launch(args);
    }
}